[<<Previous Entry]
[^^Up^^]
[Next Entry>>]
[Menu]
[About The Guide]
ARRAYS
FlexFile supports an implementation of strongly typed
multi-dimensional arrays. This array system is not to be
looked at as a replacement for the Clipper array system.
Clipper's array system is very powerful and it should not be
construed that FlexFile arrays will supersede the Clipper
system. Rather, FlexFile arrays should be used when the array
structure is regular, all the elements are of the same type,
and the array is very large.
Under no circumstance should you use FlexFile's "S"tring type array in
Clipper 5.0x. Each string element of the array is not handled by the
VMM system, and, therefore, the Clipper counterpart will take less
memory. All other FlexFile arrays can be swapped, when necessary, by
Clipper's VMM system.
Why Use FlexFile Arrays
FlexFile arrays are the only arrays to use if your array must
exceed Clipper's limit of 4029 elements. For example, a
FlexFile array of logicals allows over 500,000 elements. In
addition, each element of FlexFile array is at least six bytes
smaller than its Clipper counter part and at most thirteen
bytes and 7 bits smaller. See Appendix B for a list of the
sizes of each type of FlexFile array.
Clipper sees Flexfile arrays as regular variables. Therefore,
you pass a Flexfile arrays by value (unless you
pass-by-reference using the @ symbol) and you can return a
FlexFile array as though it were a simple Clipper variable.
Because these arrays are typically large, it is best to pass
them by reference in order to avoid duplicating their content
in memory.
The one exception to this is FlexFile's string type arrays.
These arrays pose a unique problem which is discuss below (See
FlexFile String Arrays).
Array indexes
A "subscript" or an "index" refers to a particular element of
an array. For example, Clipper refers to the third element of
a single dimensional array as ArrayName[3]. In this case, [3]
is a subscript of the array ArrayName.
Subscripts may be passed using either of two different
methods. Both methods are valid at any time. The method to
use depends largely on whether your array is single or
multi-dimensional.
If the array is a single dimensional array, then you define
and index position into that array exactly as you would
imagine. For example, if you want to store 98.6 to the fifth
element of a single dimensional floating point type array, the
following line would be fine:
nTemperature = 98.6
nPatient = 5
A_STORE( aTemps, nTemperature, nPatient )
However, if the array is multi-dimensional it is necessary to
pass the index via the A_() function. For example, if you
want to store the temperature of the fifth patient on the
third day:
A_STORE( aTemps, 98.6, A_( 5, 3 ) )
It is not wise to try to figure out the actual integer offset
of an element even though FlexFile would accept it; FlexFile
does this very fast on its own. In addition, remember element
A_( 5, 3 ) is not the same element as A_(3, 5), and rarely, if
ever, will either array index refer to the fifteenth element
as it is laid out in memory.
Understanding FlexFile Arrays
FlexFile arrays are similar to the arrays in languages such as
C or Pascal. The array is one block of memory (with the
exception of string arrays), and each element in the array
must be of the same type.
There is an analogy relating multi-dimensional arrays to a set
of encyclopedias that helps in understanding and describing
their use. This analogy is especially helpful in
understanding arrays that span into the fourth dimension.
Imagine that you have a character array. First, do not
confuse character arrays and string arrays. A string array is
an array of pointers that point to strings of varying length
that reside in random positions in memory. The string array
is actually an array of pointers and not an array of strings.
Each element points to a string of any length.
A character array is a matrix of one byte storage locations
where each byte can hold one ASCII character. In the analogy
of the encyclopedias, each letter is an element, a group of
letters that form words make up one row of text. That one
line implies the first dimension. Likewise, A group of lines
that makes up one page implies the second dimension, a group
of pages that makes up one volume implies the third dimension,
and all the volumes in the set of encyclopedias implies the
fourth dimensions. We could continue the analogy into the
fifth dimension: a set of Britannica's next to The World Book
set implies a magnitude of two in the fifth dimension.
You will often see, in the Array Function Reference chapter,
the concept of "wrapping". For example, A_SCAN() will wrap at
the end of one line to the beginning of the next, and at the
end of one page it will wrap to the top of the next page. All
functions that work with wrapping look at the array as it is
laid out in memory.
It is important to dimension your arrays with this
understanding in mind: the last dimension listed in the
declaration varies the smallest step in memory. To declare
the array for an encyclopedia you would want to declare it as
follows:
vols := 26
pages := 150
lines := 80
chars := 95
WorldBook = A_DECLARE( 'C', vols, pages, lines, chars )
This declaration of a character array is actually illegal
because the array would exceed memory, however, it is
important to see how and why the dimensions are in the order
they are in. The <chars> variable is last in order to insure
that each character is next to its proper neighbor in memory.
As far as A_STORE()ing and A_RETRIEVE()ing each character, the
layout makes little difference. However, when you need to do
something like an A_FILL() (for a blank line), this layout
becomes critical.
Lets say, for example, we want the fifth and sixth lines on
the fifteenth page of the fourth volume to be filled with
spaces.
A_FILL( WorldBook, ' ', A_( 4, 15, 5, 1 ), 2 * lines )
This function fills the 160 characters following the specified
location. Because the fill always begins at a point in memory
and moves to the next set of contiguous positions in memory,
it becomes critical how the array was declared. For example,
if we switch the order of the <lines> and <chars> in the
declaration, and then perform the A_FILL(), the fill would put
one space on each line for 160 lines instead of one space for
each character for 160 characters.
FlexFile String arrays (pointer arrays)
Arrays of strings in FlexFile pose a peculiar problem. When
the array is declared, FlexFile allocates memory for four
bytes per element. These four bytes originally point to
nothing (null). When you A_STORE() a string to an element,
however, new memory is allocated for the string. This memory
does not reside within the array, but rather, at some random
location in memory. FlexFile knows where this is because it
stores a pointer in the array which points to the new data.
A problem arises because the array itself is a Clipper
variable and has the scope of a Clipper variable. If you
release this variable or allow it to fall out of scope,
Clipper does not know that it was pointing to your strings,
and so, Clipper releases the array of pointers without
releasing the strings that it points to. In order to avoid
this, it is necessary to A_KILL() a string array before
allowing it to fall out of scope or be released.
This page created by ng2html v1.05, the Norton guide to HTML conversion utility.
Written by Dave Pearson